package com.example.mymusicdisplay.service;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.RemoteViews;

import androidx.core.app.NotificationManagerCompat;

import com.example.mymusicdisplay.MainActivity;
import com.example.mymusicdisplay.R;
import com.example.mymusicdisplay.data.MusicData;
import com.example.mymusicdisplay.utils.MediaPlayerUtil;
import com.example.mymusicdisplay.utils.MusicUtils;
import com.example.mymusicdisplay.view.LocalMusicFragment;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class PlayMusicService extends Service {
    private static final String TAG = "PlayMusicService";
    private static final String NOTIFICATION_ID = "NOTIFICATION_ID";

    private PlayMusicBinder mPlayMusicBinder = new PlayMusicBinder();
    private List<MusicData> mMusicDataList = new ArrayList<>();

    private Timer mTimer;

    private TimerTask mTimerTask;

    private int mPosition = 0;
    @SuppressLint("RemoteViewLayout")
    private RemoteViews mRemoteViews;
    private NotificationManager mManager;
    private Notification.Builder mBuilder;
    private Notification mNotification;
    private MusicListener mMusicListener;

    public class PlayMusicBinder extends Binder {
        public PlayMusicService getService() {
            return PlayMusicService.this;
        }
    }

    public PlayMusicService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("action");
        registerReceiver(mReceiver, intentFilter);
    }

    public void setPosition(int position) {
        mPosition = position;
    }

    public void setMusicList(List<MusicData> musicDataList) {
        if (musicDataList != null) {
            mMusicDataList.clear();
            mMusicDataList.addAll(musicDataList);
        }
    }

    public void play() {
        try {
            Log.d(TAG, "play: ");
            MediaPlayerUtil.getInstance().setAudioStreamType(AudioManager.STREAM_MUSIC);
            MediaPlayerUtil.getInstance().reset();
            MediaPlayerUtil.getInstance().setDataSource(mMusicDataList.get(mPosition).getUrl());
            if (mMusicListener != null) {
                if (mMusicDataList.size() > 0) {
                    mMusicListener.onPositionChanged(mMusicDataList.get(mPosition), mPosition);
                }
            } else {
                Log.e(TAG, "next: mMusicListener is null");
            }
            MediaPlayerUtil.getInstance().prepareAsync();
            MediaPlayerUtil.getInstance().setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    Log.d(TAG, "onPrepared: ");
                    if (mRemoteViews == null) {
                        startForeground();
                    } else {
                        Log.d(TAG, "onPrepared: mRemoteViews is not null");
                    }
                    MediaPlayerUtil.getInstance().start();
                    if (mMusicListener != null) {
                        mMusicListener.onPlayStateChanged(true);
                    } else {
                        Log.e(TAG, "play: mMusicListener is null");
                    }
                    updateMusicData();
                }
            });

            startTimerTask();

            MediaPlayerUtil.getInstance().setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    next();
                }
            });

            MediaPlayerUtil.getInstance().setOnErrorListener(new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
                    return true;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void startTimerTask() {
        if (mTimerTask == null && mTimer == null) {
            mTimer = new Timer();
            mTimerTask = new TimerTask() {
                @Override
                public void run() {
                    if (mMusicListener != null) {
                        mMusicListener.onProgressChanged(MediaPlayerUtil.getInstance().getCurrentPosition());
                    }
                }
            };
            mTimer.schedule(mTimerTask, 100, 100);
        }
    }

    public void start() {
        if (!MediaPlayerUtil.getInstance().isPlaying()) {
            MediaPlayerUtil.getInstance().start();
            if (mMusicListener != null) {
                mMusicListener.onPlayStateChanged(true);
            } else {
                Log.e(TAG, "start: mMusicListener is null");
            }
            startTimerTask();
            updateMusicData();
        } else {
            Log.d(TAG, "start: media player is playing");
        }
    }

    public void next() {
        Log.d(TAG, "next: ");
        mPosition = mPosition == mMusicDataList.size() - 1 ? 0 : mPosition + 1;
        releaseTimer();
        play();
    }

    public void before() {
        Log.d(TAG, "before: ");
        mPosition = mPosition == 0 ? 0 : mPosition - 1;
        releaseTimer();
        play();
    }

    public void pause() {
        releaseTimer();
        if (MediaPlayerUtil.getInstance() != null && MediaPlayerUtil.getInstance().isPlaying()) {
            MediaPlayerUtil.getInstance().pause();
            if (mMusicListener != null) {
                mMusicListener.onPlayStateChanged(false);
            } else {
                Log.e(TAG, "pause: mMusicListener is null");
            }
        }
        updateMusicData();
    }

    private void releaseTimer() {
        if (mTimerTask != null) {
            mTimerTask.cancel();
            mTimerTask = null;
        }
        if (mTimer != null) {
            mTimer.purge();
            mTimer.cancel();
            mTimer = null;
        }
    }

    @SuppressLint("RemoteViewLayout")
    public void startForeground() {
        PendingIntent pendingIntent = PendingIntent
            .getActivity(this, 0,
                new Intent(this, MainActivity.class),
                PendingIntent.FLAG_CANCEL_CURRENT);

        mManager = (NotificationManager)
            getSystemService(Context.NOTIFICATION_SERVICE);
        mRemoteViews = new RemoteViews(getPackageName(), R.layout.notification_layout);
        updateMusicData();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel =
                new NotificationChannel(NOTIFICATION_ID, "MY_MUSIC",
                    NotificationManager.IMPORTANCE_HIGH);
            mManager.createNotificationChannel(channel);
            mBuilder = new Notification.Builder(this, channel.getId());
            mBuilder.setCustomBigContentView(mRemoteViews)
                .setOngoing(true)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent);
            mNotification = mBuilder.build();
            mManager.notify(1, mNotification);
        }
    }

    public void updateMusicData() {
        Log.d(TAG, "updateMusicData: mPosition = " + mPosition);
        mRemoteViews.setTextViewText(R.id.notification_music_name, mMusicDataList.get(mPosition).getSingName());

        mRemoteViews.setTextViewText(R.id.notification_music_singer, mMusicDataList.get(mPosition).getSinger());

        if (MediaPlayerUtil.getInstance().isPlaying()) {
            Log.d(TAG, "updateMusicData: isPlaying");
            mRemoteViews.setImageViewResource(R.id.notification_music_state, R.drawable.notification_play);
        } else {
            Log.d(TAG, "updateMusicData: isNotPlaying");
            mRemoteViews.setImageViewResource(R.id.notification_music_state, R.drawable.notification_pause);
        }
        Bitmap musicCover = MusicUtils.getArtwork(this,
            mMusicDataList.get(mPosition).getSingId(),
            mMusicDataList.get(mPosition).getAlbumId(), true, false);
        mRemoteViews.setImageViewBitmap(R.id.notification_music_cover, musicCover);
        mRemoteViews.setOnClickPendingIntent(R.id.notification_music_before, getPendingIntent(this, LocalMusicFragment.NOTIFICATION_PRE_MUSIC));
        mRemoteViews.setOnClickPendingIntent(R.id.notification_music_state, getPendingIntent(this, LocalMusicFragment.NOTIFICATION_PLAY));
        mRemoteViews.setOnClickPendingIntent(R.id.notification_music_next, getPendingIntent(this, LocalMusicFragment.NOTIFICATION_NEXT_MUSIC));
        NotificationManagerCompat manager = NotificationManagerCompat.from(this);
        if (mNotification != null) {
            manager.notify(1, mNotification);
        }
    }

    private PendingIntent getPendingIntent(Context context, int state) {
        Intent intent = new Intent();
        intent.setAction(LocalMusicFragment.NOTIFICATION_ACTION);
        Bundle bundle = new Bundle();
        bundle.putInt(LocalMusicFragment.NOTIFICATION_BTN_STATE, state);
        intent.putExtras(bundle);
        PendingIntent pendingIntent = null;
        switch (state) {
            case LocalMusicFragment.NOTIFICATION_PRE_MUSIC:
                pendingIntent = PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                break;
            case LocalMusicFragment.NOTIFICATION_PLAY:
                pendingIntent = PendingIntent.getBroadcast(context, 2, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                break;
            case LocalMusicFragment.NOTIFICATION_NEXT_MUSIC:
                pendingIntent = PendingIntent.getBroadcast(context, 3, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                break;
        }
        return pendingIntent;
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "onReceive: BroadcastReceiver");
            if (intent.getAction() != null) {
                switch (intent.getIntExtra("btn_state", -1)) {
                    case 0:
                        if (MediaPlayerUtil.getInstance().isPlaying()) {
                            pause();
                        } else {
                            start();
                        }
                        break;
                    case 1:
                        before();
                        break;
                    case 2:
                        next();
                        break;
                    default:
                        break;
                }
            }
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return mPlayMusicBinder;
    }

    public MediaPlayer getMediaPlayer() {
        return MediaPlayerUtil.getInstance();
    }

    public int getPosition() {
        return mPosition;
    }

    public RemoteViews getRemoteViews() {
        return mRemoteViews;
    }

    public void setMusicListener(MusicListener musicListener) {
        mMusicListener = musicListener;
    }

    public interface MusicListener {
        //播放状态
        void onPlayStateChanged(boolean status);

        //当前播放位置
        void onPositionChanged(MusicData musicData, int position);

        //当前播放进度
        void onProgressChanged(int progress);
    }
}